const { RTCAudioSource } = require("wrtc").nonstandard;
const ffmpeg = require("fluent-ffmpeg");

const sampleRate = 48000;

class NodeWebRtcAudioSource extends RTCAudioSource {
  constructor() {
    super();
    this.command = null;
    this.cache = Buffer.alloc(0);
    this.ffstream = null;
    this.isStarting = false;
    this.isStopping = false;
  }

  createTrack() {
    const track = super.createTrack();
    return track;
  }

  async start() {
    if (this.isStarting) {
      logger.warn("WebRTC Audio Source 正在启动中，跳过重复启动");
      return;
    }
    
    if (this.command !== null) {
      await this.stop();
    }
    
    this.isStarting = true;
    logger.info("WebRTC Audio Microphone Start");

    try {
      // 使用延迟初始化避免_ffmpegProc访问错误
      await this.initFFmpegCommand();
      
    } catch (error) {
      logger.error(`启动WebRTC Audio Source失败: ${error.message}`);
      this.isStarting = false;
      this.cleanup();
      throw error;
    }
  }

  async initFFmpegCommand() {
    return new Promise((resolve, reject) => {
      try {
        this.command = ffmpeg("default")
          .inputFormat("pulse")
          .audioChannels(1)
          .audioFrequency(sampleRate)
          .audioCodec("pcm_s16le")
          .outputFormat("s16le")
          .on("start", (commandLine) => {
            logger.info("WebRTC Audio Microphone Open");
            logger.debug(`FFmpeg命令: ${commandLine}`);
            this.isStarting = false;
            
            // 延迟创建pipe流确保进程完全启动
            setTimeout(() => {
              try {
                if (this.command && !this.isStopping) {
                  this.ffstream = this.command.pipe();
                  this.setupStreamHandlers();
                  this.startDataProcessing();
                  resolve();
                }
              } catch (error) {
                logger.error(`创建FFmpeg流失败: ${error.message}`);
                reject(error);
              }
            }, 100); // 100ms延迟确保进程完全启动
          })
          .on("error", (err) => {
            logger.error(`WebRTC Audio Microphone error: ${err.message}`);
            this.handleError(err);
            reject(err);
          })
          .on("stderr", (stderrLine) => {
            // 只记录重要的错误信息
            if (stderrLine.includes('Error') || stderrLine.includes('error')) {
              logger.warn(`WebRTC Audio FFmpeg stderr: ${stderrLine}`);
            }
          })
          .on("end", () => {
            logger.info("WebRTC Audio Microphone processing finished");
            this.cleanup();
          });

        // 不在这里调用pipe()，等待start事件后再调用
        
      } catch (error) {
        logger.error(`创建FFmpeg命令失败: ${error.message}`);
        reject(error);
      }
    });
  }

  setupStreamHandlers() {
    if (!this.ffstream) return;
    
    this.ffstream.on("data", (buffer) => {
      if (this.command && !this.isStopping) {
        this.cache = Buffer.concat([this.cache, buffer]);
      }
    });
    
    this.ffstream.on("drain", () => {
      logger.debug("WebRTC Audio Microphone stream drain");
    });
    
    this.ffstream.on("error", (error) => {
      logger.error(`WebRTC Audio Microphone stream error: ${error.message}`);
      this.handleError(error);
    });
    
    this.ffstream.on("finish", () => {
      logger.info("WebRTC Audio Microphone stream finish");
      this.cleanup();
    });
    
    this.ffstream.on("close", () => {
      logger.debug("WebRTC Audio Microphone stream closed");
    });
  }

  startDataProcessing() {
    const processData = () => {
      if (this.isStopping || !this.command) {
        return;
      }
      
      try {
        while (this.cache.length >= 960) {
          const buffer = this.cache.slice(0, 960);
          this.cache = this.cache.slice(960);
          
          const samples = new Int16Array(new Uint8Array(buffer).buffer);
          this.onData({
            bitsPerSample: 16,
            sampleRate,
            channelCount: 1,
            numberOfFrames: samples.length,
            type: "data",
            samples,
          });
        }
      } catch (error) {
        logger.error(`音频数据处理错误: ${error.message}`);
      }
      
      if (this.command && !this.isStopping) {
        setTimeout(() => processData(), 10);
      }
    };
    
    processData();
  }

  handleError(error) {
    logger.error(`FFmpeg进程错误: ${error.message}`);
    
    // 根据错误类型进行不同的处理
    if (error.message.includes('Device or resource busy')) {
      logger.warn('音频设备被占用，尝试重启音频源');
      setTimeout(() => this.restart(), 2000);
    } else if (error.message.includes('No such file or directory')) {
      logger.error('音频设备不存在，请检查麦克风连接');
    } else {
      // 通用错误处理
      this.cleanup();
    }
  }

  async restart() {
    logger.info('重启WebRTC Audio Source');
    await this.stop();
    setTimeout(() => this.start(), 1000);
  }

  async stop() {
    if (this.isStopping) {
      logger.debug('WebRTC Audio Source 正在停止中');
      return;
    }
    
    this.isStopping = true;
    logger.info("WebRTC Audio Source stop");

    return new Promise((resolve) => {
      const cleanup = () => {
        this.cleanup();
        this.isStopping = false;
        resolve();
      };

      if (this.command) {
        try {
          // 使用更温和的SIGTERM而不是SIGHUP
          this.command.kill('SIGTERM');
          
          // 设置超时，如果进程没有正常退出，则强制杀死
          const killTimeout = setTimeout(() => {
            logger.warn('FFmpeg进程未能正常退出，强制终止');
            try {
              if (this.command) {
                this.command.kill('SIGKILL');
              }
            } catch (e) {
              logger.debug('强制终止FFmpeg进程失败:', e.message);
            }
            cleanup();
          }, 3000);

          // 监听进程退出事件
          this.command.on('end', () => {
            clearTimeout(killTimeout);
            cleanup();
          });
          
          this.command.on('error', () => {
            clearTimeout(killTimeout);
            cleanup();
          });
          
        } catch (error) {
          logger.warn(`停止FFmpeg进程时出错: ${error.message}`);
          cleanup();
        }
      } else {
        cleanup();
      }
    });
  }

  cleanup() {
    logger.debug('清理WebRTC Audio Source资源');
    
    this.command = null;
    this.ffstream = null;
    this.cache = Buffer.alloc(0);
    this.isStarting = false;
  }
}

module.exports = NodeWebRtcAudioSource;
